﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;

#if WPF
using MessageBoxButtons = System.Windows.MessageBoxButton;
using MessageBoxIcon = System.Windows.MessageBoxImage;
#endif

#if WPF
using System.Windows.Input;
using DevExpress.Xpf.DemoBase.DemoData;
#else
using System.Windows.Forms;
using DemoCenter;
#endif

namespace DevExpress.DemoCenter {
    public class StartDemoHelper {
        static string relativePath = null;

        public static string GetDemoFullPathName(string demoName) {
            return DemosPath + demoName;
        }
        public static string XafDataPath {
            get { return RelativeDemosPath + "..\\eXpressApp Framework\\Data\\"; }
        }
        public static string GetXafDemoFullPathName(string demoName) {
            return DemosPath + "..\\eXpressApp Framework\\" + demoName;
        }
        public static string DemosPath {
            get { return AppDomain.CurrentDomain.BaseDirectory + RelativeDemosPath; }
        }
        public static string RelativeDemosPath {
            get {
                if(relativePath != null)
                    return relativePath;
                relativePath = "";
                for(int i = 0; i < 10; i++) {
                    string s = AppDomain.CurrentDomain.BaseDirectory + relativePath + "Data";
                    if(Directory.Exists(s))
                        break;
                    relativePath += "..\\";
                }
                return relativePath;
            }
        }
        static readonly string[] filesWithCommandLineArguments = new string[] { "GridMainDemo.exe" };
        [DllImport("user32.dll")]
        static extern uint MsgWaitForMultipleObjects(uint nCount, IntPtr[] pHandles, bool bWaitAll, uint dwMilliseconds, uint dwWakeMask);
        [DllImport("user32.dll", SetLastError = true)]
        static extern void SwitchToThisWindow(IntPtr hwind, bool fAltTab);
        public static void StartApplication(string moduleName) {
            string correctModuleName = string.IsNullOrEmpty(moduleName) ? string.Empty : ModuleUrlHelper.CorrectURLByModuleName(moduleName);
            string fileName = string.IsNullOrEmpty(correctModuleName) ? string.Empty : GetDemoFullPathName(correctModuleName);
            if(!string.IsNullOrEmpty(fileName) && !File.Exists(fileName) && !Directory.Exists(fileName))
                fileName = GetXafDemoFullPathName(correctModuleName);
            if(string.IsNullOrEmpty(fileName) || !File.Exists(fileName) && !Directory.Exists(fileName)) {
                ShowMessageBox(string.Format("File {0} is not found.", correctModuleName), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            Cursor current = ApplicationCursor;
            ApplicationCursor = WaitCursor;
            try {
                string workingDirectory = null;
                if(ModuleUrlHelper.IsUrl(moduleName)) {
                    fileName = WebDevServerHelper.PrepareDemoPathForProcessing(fileName, moduleName);
                } else {
                    fileName = fileName.Replace('\\', '/');
                    int k = fileName.LastIndexOf("/");
                    if(k >= 0)
                        workingDirectory = fileName.Remove(k);
                }
                ProcessStartInfo psi = new ProcessStartInfo(fileName);
                psi.WorkingDirectory = workingDirectory != null ? workingDirectory : AppDomain.CurrentDomain.BaseDirectory;
                bool hasArguments = false;
                foreach(string name in filesWithCommandLineArguments)
                    if(fileName.IndexOf(name) > 0) {
                        hasArguments = true;
                        break;
                    }
                if(hasArguments)
                    psi.Arguments = "-demo";
                WaitForWindowAppears(Process.Start(psi));
            } catch(Exception e) {
                ApplicationCursor = current;
                ShowMessageBox(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } finally {
                ApplicationCursor = current;
            }
        }
#if WPF
        static Cursor ApplicationCursor {
            get { return Mouse.OverrideCursor; }
            set { Mouse.OverrideCursor = value; }
        }
        static Cursor WaitCursor { get { return Cursors.Wait; } }
        static void ShowMessageBox(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) {
            MessageBox.Show(message, caption, buttons, icon);
        }
#else
        static Cursor ApplicationCursor {
            get { return Cursor.Current; }
            set { Cursor.Current = value; }
        }
        static Cursor WaitCursor { get { return Cursors.WaitCursor; } }
        static void ShowMessageBox(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) {
            MessageBox.Show(message, caption, buttons, icon);
        }
#endif
        static long GetMonotonicTime() {
            return DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond;
        }
        static void WaitForWindowAppears(Process process) {
            if(process == null) return;
            IntPtr[] handles = new IntPtr[] { process.Handle };
            try {
                while(true) {
                    process.Refresh();
                    ApplicationCursor = WaitCursor;
                    MsgWaitForMultipleObjects((uint)handles.Length, handles, true, 250, 0xff);
                    if(!process.MainWindowHandle.Equals(IntPtr.Zero)) {
                        SwitchToThisWindow(process.MainWindowHandle, true);
                        return;
                    }
                }
            } catch(Exception) { }
        }
    }
}
